<?php
/**
 * Created by PhpStorm.
 * User: hhcycj
 * Date: 2018/4/4
 * Time: 21:10
 */

namespace ws;

/**
 * task 是 Swoole\Server 类定义的，只要基础这个类的Server都可以使用task
 * Class ws
 * @package ws
 */
class ws
{
    const host = "0.0.0.0";
    const PORT = 8812;

    public $ws = null;

    public function __construct()
    {
        $this->ws = new \swoole_websocket_server(self::host, self::PORT);

        $this->set();

        $this->ws->on('open', [$this, 'onOpen']);
        $this->ws->on('message', [$this, 'onMessage']);
        $this->ws->on('close', [$this, 'onClose']);

        // 使用Task功能，必须先设置 task_worker_num，并且必须设置Server的onTask和onFinish事件回调函数。
        $this->ws->on('task', [$this, 'onTask']);
        $this->ws->on('finish', [$this, 'onFinish']);

        $this->ws->start();

    }

    public function set(){
        $this->ws->set([
            'worker_num' => 4,
            'task_worker_num' => 8,
            'document_root' => '/var/www/swoole/data',
            'enable_static_handler' => true,
        ]);
    }

    /**
     * 当WebSocket客户端与服务器建立连接并完成握手后会回调此函数。
     */
    public function onOpen($ws, $request){
        echo "open: fd{$request->fd}\n";
    }

    /**
     *  当服务器收到来自客户端的数据帧时会回调此函数。
     * @param $ws
     * @param $frame swoole_websocket_frame对象，包含了客户端发来的数据帧信息
     * User: hhcycj
     */
    public function onMessage($ws, $frame){
        echo "message: receive from {$frame->fd}:{$frame->data}, opcode:{$frame->opcode}, finish:{$frame->finish}\n";

        // todo 10s
        $data = [
            'task' => 1,
            'fd'   => $frame->fd,
        ];

        // 异步执行任务
        $ws->task($data);

        $ws->push($frame->fd, "this is server");

        echo "onMessage end \n";
    }

    /**
     * 执行异步任务
     * @param $ws 这里我们在websocket里实现，此时就是websocket对象
     * @param $task_id 是任务ID，由swoole扩展内自动生成，用于区分不同的任务。$task_id和$src_worker_id组合起来才是全局唯一的，不同的worker进程投递的任务ID可能会有相同
     * @param $src_worker_id 来自于哪个worker进程
     * @param $data 是任务的内容
     * @return string
     */
    public function onTask($ws, $task_id, $src_worker_id, $data){
        echo "onTask \n";
        sleep(10);
        return "onTask task_id={$task_id}, src_worker_id={$src_worker_id}"; // 告诉worker 进程
    }

    /**
     * 任务执行完成后回调的函数
     * @param $ws
     * @param $task_id
     * @param $data  这个data是onTask返回的内容
     */
    public function onFinish($ws, $task_id, $data){
        echo "taskId:{$task_id}\n";
        echo "onFinish：{$data}\n"; // onTask return的内容
    }


    /**
     * @param $ser
     * @param $fd
     * User: hhcycj
     */
    public function onClose ($ser, $fd) {
        echo "client {$fd} closed\n";
    }
}

$obj = new ws();